package com.tjvib.view.activity;

import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.TextView;

import com.tjvib.Constants;
import com.tjvib.R;
import com.tjvib.base.BaseActivity;
import com.tjvib.bean.ResBean;
import com.tjvib.common.LoadingCallback;
import com.tjvib.presenter.BasePresenter;
import com.tjvib.util.LogUtil;
import com.tjvib.util.Manager.DataSetManager;
import com.tjvib.util.Manager.UserManager;
import com.tjvib.util.PoiUtil;
import com.tjvib.util.ToastUtil;
import com.tjvib.view.dialog.HintDialog;
import com.tjvib.view.dialog.LoadingDialog;
import com.tjvib.widget.TitleLayout;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MassActivity extends BaseActivity implements LoadingCallback {

    private Button mass_btn_confir, mass_btn_export;
    private TextView mass_tv_weight, mass_tv_wmat_a, mass_tv_gmat_ab, mass_tv_wmatlen, mass_tv_gmatlen;
    private Spinner mass_sp_peo, mass_sp_peodir, mass_sp_stru, mass_sp_strudir, mass_sp_std;
    private EditText mass_et_znb, mass_et_tz, mass_et_hz1, mass_et_hz2, mass_et_hz3,
            mass_et_cs, mass_et_cd, mass_et_kd;
    private TitleLayout mass_tit;
    private static LoadingDialog loadingDialog = null;
    private static int size;
    private static double a, b, ori_a, ori_b;

    private DataSetManager dataSetManager = DataSetManager.getInstance();
    private final ExecutorService executorService = Executors.newSingleThreadExecutor();
    private boolean isExporting = false;


    TextWatcher tw = new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
        @Override
        public void afterTextChanged(Editable editable) {
            if(isFull()) mass_btn_confir.setBackground(getResources().getDrawable(R.drawable.selector_purple_rad40));
        }
    };

    AdapterView.OnItemSelectedListener onItemSelectedListener = new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            if(isFull() && !mass_sp_peo.getSelectedItem().toString()
                    .equals(mass_sp_stru.getSelectedItem().toString()))
                mass_btn_confir.setBackground(getResources().getDrawable(R.drawable.selector_purple_rad40));
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {}
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    protected int initLayout() {
        return R.layout.activity_mass;
    }

    @Override
    protected boolean initView() {
        mass_tit = findViewById(R.id.mass_tit);
        mass_tit.setTitle(getIntent().getStringExtra("METHOD"));

        mass_btn_export = findViewById(R.id.mass_btn_export);
        mass_btn_export.setOnClickListener(v -> {
            if (isExporting) {
                ToastUtil.show("导出任务正在进行中，请稍后");
                return;
            }
            isExporting = true;
            if (isFull()) {
                if (mass_sp_peo.getSelectedItem().toString()
                        .equals(mass_sp_stru.getSelectedItem().toString())) {
                    showErrorDialog("人体测传感器不能与结构侧传感器相同！");
                } else {
                    double hz1 = Double.parseDouble(mass_et_hz1.getText().toString().trim());
                    double hz2 = Double.parseDouble(mass_et_hz2.getText().toString().trim());
                    double hz3 = Double.parseDouble(mass_et_hz3.getText().toString().trim());
                    if(hz1 < hz2 && hz2 < hz3) {
                        executorService.submit(() -> {
                            try {
                                FileReadWriteTask fileReadWriteTask = new FileReadWriteTask();
                                fileReadWriteTask.execute();
                                runOnUiThread(() -> {
                                    ToastUtil.show("导出成功");
                                    isExporting = false;
                                });
                            } catch (Exception e) {
                                LogUtil.e("导出失败", e);
                                runOnUiThread(() -> {
                                    ToastUtil.show("导出失败，请重试");
                                    isExporting = false;
                                });
                            }
                        });
                    }else ToastUtil.show("结构前三阶频率必须是递增序列！");
                }
            } else {
                showErrorDialog("请输入完整参数并得到结果！");
                isExporting = false;
            }
        });

        mass_btn_confir = findViewById(R.id.mass_btn_confir);
        mass_btn_confir.setOnClickListener(v-> showResult());

        mass_sp_peo = findViewById(R.id.mass_sp_peo);
        mass_sp_peodir = findViewById(R.id.mass_sp_peodir);
        mass_sp_stru = findViewById(R.id.mass_sp_stru);
        mass_sp_strudir = findViewById(R.id.mass_sp_strudir);
        mass_sp_std = findViewById(R.id.mass_sp_std);

        mass_et_tz = findViewById(R.id.mass_et_tz);
        mass_et_hz1 = findViewById(R.id.mass_et_hz1);
        mass_et_hz2 = findViewById(R.id.mass_et_hz2);
        mass_et_hz3 = findViewById(R.id.mass_et_hz3);
        mass_et_znb = findViewById(R.id.mass_et_znb);
        mass_et_cs = findViewById(R.id.mass_et_cs);
        mass_et_cd = findViewById(R.id.mass_et_cd);
        mass_et_kd = findViewById(R.id.mass_et_kd);

        mass_et_tz.addTextChangedListener(tw);
        mass_et_hz1.addTextChangedListener(tw);
        mass_et_hz2.addTextChangedListener(tw);
        mass_et_hz3.addTextChangedListener(tw);
        mass_et_znb.addTextChangedListener(tw);
        mass_et_cs.addTextChangedListener(tw);
        mass_et_cd.addTextChangedListener(tw);
        mass_et_kd.addTextChangedListener(tw);

        mass_tv_weight = findViewById(R.id.mass_tv_weight);
        mass_tv_wmat_a = findViewById(R.id.mass_tv_wmat_a);
        mass_tv_wmatlen = findViewById(R.id.mass_tv_wmatlen);
        mass_tv_gmat_ab = findViewById(R.id.mass_tv_gmat_ab);
        mass_tv_gmatlen = findViewById(R.id.mass_tv_gmatlen);
        return true;
    }

    @Override
    protected boolean initData() {
        String[] directions = {"X", "Y", "Z"};
        SpinnerAdapter directionSpinnerAdapter = new ArrayAdapter<>(this,
                R.layout.item_spinner_dropdown, directions);
        SpinnerAdapter sensorSpinnerAdapter = new ArrayAdapter<>(this,
                R.layout.item_spinner_dropdown, DataSetManager.getInstance().getSensorList());

        String[] stds = {"框架结构", "剪力墙结构", "框架剪力墙结构"};
        SpinnerAdapter stdSpinnerAdapter = new ArrayAdapter<>(this,
                R.layout.item_spinner_dropdown, stds);

        mass_sp_peo.setAdapter(sensorSpinnerAdapter);
        mass_sp_peodir.setAdapter(directionSpinnerAdapter);
        mass_sp_stru.setAdapter(sensorSpinnerAdapter);
        mass_sp_strudir.setAdapter(directionSpinnerAdapter);
        mass_sp_std.setAdapter(stdSpinnerAdapter);

        mass_sp_peo.setOnItemSelectedListener(onItemSelectedListener);
        mass_sp_peodir.setOnItemSelectedListener(onItemSelectedListener);
        mass_sp_stru.setOnItemSelectedListener(onItemSelectedListener);
        mass_sp_strudir.setOnItemSelectedListener(onItemSelectedListener);
        mass_sp_std.setOnItemSelectedListener(onItemSelectedListener);

        return true;
    }

    @Override
    protected BasePresenter genPresenter() {
        return null;
    }


    private boolean isFull(){
        if(mass_et_tz.getText().toString().isEmpty())
            ToastUtil.show("实验者体重未输入");
        else if(mass_et_hz1.getText().toString().isEmpty())
            ToastUtil.show("结构第一阶频率未输入");
        else if(mass_et_hz2.getText().toString().isEmpty())
            ToastUtil.show("结构第二阶频率未输入");
        else if(mass_et_hz3.getText().toString().isEmpty())
            ToastUtil.show("结构第三阶频率未输入");
        else if(mass_et_znb.getText().toString().isEmpty())
            ToastUtil.show("结构阻尼比未输入");
        else if(mass_et_cs.getText().toString().isEmpty())
            ToastUtil.show("结构层数未输入");
        else if(mass_et_cd.getText().toString().isEmpty())
            ToastUtil.show("实验者体重未输入");
        else if(mass_et_kd.getText().toString().isEmpty())
            ToastUtil.show("实验者体重未输入");

        return !mass_et_tz.getText().toString().isEmpty() &&
                !mass_et_hz1.getText().toString().isEmpty() &&
                !mass_et_hz2.getText().toString().isEmpty() &&
                !mass_et_hz3.getText().toString().isEmpty() &&
                !mass_et_znb.getText().toString().isEmpty() &&
                !mass_et_cs.getText().toString().isEmpty() &&
                !mass_et_cd.getText().toString().isEmpty() &&
                !mass_et_kd.getText().toString().isEmpty();
    }


    private void showResult() {
        if(isFull()) {
            if (mass_sp_peo.getSelectedItem().toString()
                    .equals(mass_sp_stru.getSelectedItem().toString())) {
                showErrorDialog("人体测传感器不能与结构侧传感器相同！");
            } else {
                mass_btn_confir.setBackground(getResources().getDrawable(R.drawable.selector_purple_rad40));

                int humanImuId = Integer.parseInt(mass_sp_peo.getSelectedItem().toString());
                int humanDirection = mass_sp_peodir.getSelectedItemPosition();
                String curStru = mass_sp_std.getSelectedItem().toString();
                double humanWeight = Double.parseDouble(mass_et_tz.getText().toString());
                double firstFrequency = Double.parseDouble(mass_et_hz1.getText().toString());
                double secondFrequency = Double.parseDouble(mass_et_hz2.getText().toString());
                double thirdFrequency = Double.parseDouble(mass_et_hz3.getText().toString());
                double dampingRatio = Double.parseDouble(mass_et_znb.getText().toString());
                int n = Integer.parseInt(mass_et_cs.getText().toString());
                double length = Double.parseDouble(mass_et_cd.getText().toString());
                double width = Double.parseDouble(mass_et_kd.getText().toString());

                new Thread(()-> dataSetManager.calculateMass(humanImuId, humanDirection, n, length, width,
                                getIntent().getDoubleExtra("T0", 0.0), humanWeight,
                                curStru, dampingRatio, firstFrequency, secondFrequency, thirdFrequency,
                                MassActivity.this)).start();
            }
        }else
            ToastUtil.show("请输入完整参数！");
    }


    @Override
    public void showLoading() {
        runOnUiThread(() -> {
            loadingDialog = new LoadingDialog(MassActivity.this);
            loadingDialog.showDialog(MassActivity.this, "正在计算...", 100);
        });
    }

    @Override
    public void dismissLoading() {
        runOnUiThread(() -> {
            if (loadingDialog != null) loadingDialog.dismiss();
        });
    }

    @Override
    public void onComplete(ResBean res) {
        runOnUiThread(() -> {
            mass_tv_weight.setText(ResBean.getString(res.getA(), "[", "]", 0) + "\n"
                    + ResBean.getString(res.getOri_a(), "(", ")", 0));

            size = Integer.parseInt(mass_et_cs.getText().toString().trim());
            a = res.getB().get(0);
            ori_a = res.getOri_b().get(0);
            b = res.getC().get(0);
            ori_b = res.getOri_c().get(0);

            mass_tv_gmatlen.setText(size + " × " + size);
            mass_tv_wmatlen.setText(size + " × " + size);
            mass_tv_wmat_a.setText(" = " + getStringValue(a, 0) + "\n(" + getStringValue(ori_a, 0) +")");
            mass_tv_gmat_ab.setText(" = " + getStringValue(-2*b, 3) + "\n(" + getStringValue(b, 3)
                    + ")\n = " + getStringValue(-2*ori_b, 3) +"\n(" + getStringValue(ori_b, 3)+")");
        });
    }

    public String getStringValue(double val, int d){
        String tmp = "" + val;
        int doc_pos = tmp.indexOf("."), e_pos = tmp.indexOf("E");
        if(d != 0) doc_pos += 1;
        if(e_pos == -1) return tmp.substring(0, doc_pos+d);
        else return tmp.substring(0, doc_pos+d) + tmp.substring(e_pos);
    }

    @Override
    public void onError(String res) {
        runOnUiThread(() -> showErrorDialog(res));
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        executorService.shutdownNow();
    }


    private class FileReadWriteTask extends AsyncTask<Void, Void, Void> {
        private LoadingDialog loadingDialog = null;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            runOnUiThread(() -> {
                loadingDialog = new LoadingDialog(MassActivity.this);
                loadingDialog.showDialog(MassActivity.this, "正在输出报告...", 5);
            });
        }

        @Override
        protected Void doInBackground(Void... voids) {
            SimpleDateFormat sdf = new SimpleDateFormat();
            sdf.applyPattern("yyyy-MM-dd HH:mm:ss");
            Date date = new Date();

            Map<String, String> replacements = new HashMap<>();
            replacements.put("【时间】", sdf.format(date));
            replacements.put("【姓名】", UserManager.getInstance().getUsername());
            replacements.put("【人体侧传感器】", mass_sp_peo.getSelectedItem().toString().trim());
            replacements.put("【人体侧传感器运动方向】", mass_sp_peodir.getSelectedItem().toString().trim());
            replacements.put("【结构侧传感器】", mass_sp_stru.getSelectedItem().toString().trim());
            replacements.put("【结构侧传感器运动方向】", mass_sp_strudir.getSelectedItem().toString().trim());

            replacements.put("【实验者体重】", mass_et_tz.getText().toString());
            replacements.put("【结构前三阶频率】", mass_et_hz1.getText().toString()+", "
                    + mass_et_hz2.getText().toString() + ", " + mass_et_hz3.getText().toString());
            replacements.put("【结构阻尼比】", mass_et_znb.getText().toString());
            replacements.put("【结构层数】", mass_et_cs.getText().toString());
            replacements.put("【结构平面长度】", mass_et_cd.getText().toString());
            replacements.put("【结构平面宽度】", mass_et_kd.getText().toString());
            replacements.put("【结构体系】", mass_sp_std.getSelectedItem().toString());
            replacements.put("【前三阶模态质量】", mass_tv_weight.getText().toString());

            StringBuilder[] res1 = new StringBuilder[size];
            for (int i = 0; i < size; i++) {
                res1[i] = new StringBuilder();
                for (int j = 0; j < size; j++) {
                    if (j == i) res1[i].append(a);
                    else res1[i].append("0");
                    if (j < size - 1) res1[i].append(", ");
                }
                res1[i].insert(0, "第 "+(i+1)+" 行 "+"[").append("]");
                if(i != 0)res1[i].insert(0, "\n");
            }
            String res11 = Arrays.toString(res1);
            replacements.put("【质量矩阵】", "矩阵尺寸："+size+" × "+size+"\n"+res11.substring(1, res11.length()-1));

            StringBuilder[] res2 = new StringBuilder[size];
            for (int i = 0; i < size; i++) {
                res2[i] = new StringBuilder();
                for (int j = 0; j < size; j++) {
                    if(i != size-1) {
                        if (j == i - 1 || j == i + 1) res2[i].append(b);
                        else if (j == i) res2[i].append(-2*b);
                        else res2[i].append("0");
                    }else{
                        if (j == i - 1) res2[i].append(b);
                        else if (j == i) res2[i].append(-b);
                        else res2[i].append("0");
                    }
                    if (j < size - 1) res2[i].append(", ");
                }
                res2[i].insert(0, "第 "+(i+1)+" 行 "+" [").append("]");
                if(i != 0) res2[i].insert(0, "\n");
            }
            String res22 = Arrays.toString(res2);
            replacements.put("【刚度矩阵】", "矩阵尺寸："+size+" × "+size+"\n"+res22.substring(1, res22.length()-1));

            synchronized (PoiUtil.class) {
                PoiUtil.replaceFieldsWithImage(null, MassActivity.this,
                        Constants.METHOD_MASS, sdf.format(date) + ".docx", replacements);
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void unused) {
            super.onPostExecute(unused);
            isExporting = false;
            if(loadingDialog != null) loadingDialog.dismiss();
            ToastUtil.show("报告已保存");
        }
    }
}